﻿#include "StdAfx.h"
#include "Dbc.h"
#include "Stmt.h"
#include "Lite_Util.h"
#include "Globalvf.h"

//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// DBC 생성자/파괴자. 생성/삭제.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// STMT 생성.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
CDBC::CDBC(const int nMyIndex)
{
	//==================================================
	// 작동을 위한 변수들 초기화.
	//==================================================
	magic = 0;			/**< Magic cookie */
    env = NULL;			/**< Pointer to environment */
	version = 0 ;		/**< SQLITE version number */
    memset(dbname,0,50);		/**< SQLITE database name */
    memset(dsn,0,50);			/**< ODBC data source name */
    timeout = 0;		/**< Lock timeout value */
    t0 = 0;			/**< Start time for SQLITE busy handler */
    busyint = 0;		/**< Interrupt busy handler from SQLCancel() */
    //m_stmt = NULL;		/**< STMT list of this DBC */
    naterr = 0;			/**< Native error code */
    memset(sqlstate,0,6);		/**< SQL state for SQLError() */
    memset(logmsg,0,1024);	/**< Message for SQLError() */
    nowchar = 0;		/**< Don't try to use WCHAR */
    dobigint = 0;		/**< Force SQL_BIGINT for INTEGER columns */
    shortnames = 0;		/**< Always use short column names */
    longnames = 0;		/**< Don't shorten column names */
    nocreat = 0;		/**< Don't auto create database file */
    fksupport = 0;		/**< Foreign keys on or off */
    curtype = 0;		/**< Default cursor type */
    step_enable = 0;		/**< True for sqlite_compile/step/finalize */
    oemcp = 0;			/**< True for Win32 OEM CP translation */
    s3stmt_needmeta = 0;	/**< True to get meta data in s3stmt_step(). */
    trace = NULL;		/**< sqlite3_trace() file pointer or NULL */
    xcelqrx = 0;
	for( int i = 0 ; i < STMT_COUNT; i ++)
	{
		m_pStmt[i] = NULL;
	}
	//==================================================
	// 초기화 설정
	//==================================================
	m_nMyIndex = nMyIndex;
    const char *verstr;
    int maj = 0, min = 0, lev = 0;
    curtype = SQL_CURSOR_STATIC;
    verstr = util_Version();
    sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
    version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
    magic = DBC_MAGIC;
	//==================================================
	/// Lite_Dbc 생성.
	//==================================================
	m_pEngDbc = lite_CreateDBC();
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// 파괴자
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
CDBC::~CDBC(void)
{
	for( int i = 0 ; i < STMT_COUNT; i ++)
	{
		if( NULL != m_pStmt[i])
			delete m_pStmt[i];
	}
	lite_CloseDBC(m_pEngDbc);
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Util 함수.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// 에러 세팅
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
void CDBC::SetErr(char * pErr)
{
	memset(m_szErr,0,128);
	STRCPY(m_szErr,pErr,128);
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Open 검사.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL CDBC::IsOpen()
{
	return m_bOpen;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Open 검사.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
const char * CDBC::GetErr()
{
	return m_szErr;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// STMT 생성/삭제.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// STMT 생성.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
CSTMT * CDBC::CreateStmt()
{
	for( int i = 0 ; i < STMT_COUNT ;i++)
	{
		if( NULL == m_pStmt[i])
		{
			m_pStmt[i] = new CSTMT(i,(CDBC*)this);
			return m_pStmt[i];
		}
		else if( m_pStmt[i]->m_bUse == FALSE)
		{
			m_pStmt[i]->InitStmt();
			return m_pStmt[i]; 
		}
	}
	return NULL;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// dbc 삭제.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL  CDBC::DeleteStmt(CSTMT * pStmt)
{
	if( NULL == pStmt)
		return TRUE;
	int i = pStmt->m_nMyIndex;
	if((i < 0 ) || ( i >= STMT_COUNT))
		return FALSE;
	if( NULL != m_pStmt[i])
	{
		delete m_pStmt[i];
		m_pStmt[i] = NULL;
	}
	return TRUE;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// 모든 STMT Rest한다.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
void   CDBC::ResetAllStmt()
{
	for( int i = 0 ; i < STMT_COUNT; i ++)
	{
		if( NULL != m_pStmt[i])
		{
			m_pStmt[i]->m_bUse = FALSE;
		}
	}
}

/**
	@brief  서버에 네트워크로 연결을 시도하고 로그인을 시도 한다.
	@return 성공 여부.
*/
BOOL CDBC::Open(char *pIP, /**< 서버 IP */
				int nPort, /**< 서버 Port */
				int nTimeout, /**< 연결 Time Out */
				char *pUID, /**< ID */
				char * pPWD /**< PASSWORD */
				)

{
	return TRUE;
	return lite_ConnectDB(m_pEngDbc,pIP, nPort, nTimeout,3, pUID, pPWD); // 서버와 연결 시도
}

//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Close
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
void CDBC::Close()
{
	for( int i = 0 ; i < STMT_COUNT; i ++)
	{
		if( NULL != m_pStmt[i])
		{
			m_pStmt[i]->Finalize();
		}
	}
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// 자료 및 SQL문.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// 테이블 얻기.(배열로 얻기.)
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL CDBC::GetTable(const char *pszSQL,char ***pazResult,
  int *pnRow,           
  int *pnColumn,        /* Number of result columns written here */
  char **pzErrmsg       /* Error msg written here */
)
{
	STMT *pstmt = CreateStmt();
	if( pstmt == NULL)
		return FALSE;
	if( FALSE == pstmt->Prepare(pszSQL))
	{
		*pnRow = 0;
		*pnColumn = 0;
		*pazResult = NULL; 
		return FALSE;
	}
	int nCount = 0;
	int nRow = 0;
	int nLen;
	int i = 0;
	char *p;
	*pazResult = NULL;
	CArray<char*,char*> arr;
	for(i = 0 ; i < pstmt->m_nColCount ; i ++ )
	{
		const char *pValue = pstmt->GetFieldName(i);
		nLen = strlen(pValue) + 1;

		XMALLOC(p, char *,nLen);
		strncpy_s(p,nLen,pValue,nLen);
		arr.Add(p);
		nCount ++;
	}
	pstmt->MoveNext();
	while(FALSE == pstmt->m_bMoveNextEnd)
	{
		for(i = 0 ; i < pstmt->m_nColCount ; i ++ )
		{
			const char *pValue = pstmt->Get_Column_Text(i);
			nLen = strlen(pValue) + 1;

			XMALLOC(p,char *,nLen);
			strncpy_s(p,nLen,pValue,nLen);
			arr.Add(p);
			nCount ++;
		}
		nRow ++;
		pstmt->MoveNext();
	}
	XMALLOC(*pazResult,char **,nCount+1);
	//=====================================================
	XMALLOC((*pazResult)[0],char*,sizeof(int));
	memset(*pazResult[0],'\0',sizeof(int));
	memcpy(*pazResult[0],&nCount,sizeof(int));
	//=====================================================
	for( i = 0 ; i < arr.GetCount(); i ++)
	{
		nLen = strlen(arr[i]) + 1;

		XMALLOC((*pazResult)[i+1],char*,sizeof(char)*nLen);
		strncpy_s((*pazResult)[i+1],nLen,arr[i],nLen);
	}
	*pazResult = *pazResult + 1;
	*pnRow = nRow;
	*pnColumn = pstmt->m_nColCount;
	pstmt->Finalize();
	arr.RemoveAll();
	return TRUE;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Exec 수행.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL CDBC::Exec(const char * pszSQL)
{
	return ENG_OK;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// BEGIN 수행.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL CDBC::Begin(char** pErr)
{
	/*
	if(m_bOpen == FALSE)
		return ENG_ERROR;
	STMT *pstmt = CreateStmt();
	if(pstmt == NULL)
	{
		SetErr("Fail to create STMT Object");
		return ENG_ERROR;
	}
	if ( ENG_ERROR == pstmt->WriteReadSock(ITEM_BEGIN,STAT_END,REPLY_SERVER_OK,strlen("BEGIN_OK"),"BEGIN_OK"))
	{
			SetErr(pstmt->m_pPack->szData);
			if( NULL != pErr)
				*pErr = pstmt->m_szErr;
			pstmt->Finalize();
			return ENG_ERROR;
	}
	pstmt->Finalize();
	*/
	return ENG_OK;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Commit 수행.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL CDBC::Commit(char** pErr)
{
	/*
	if(m_bOpen == FALSE)
		return ENG_ERROR;
	STMT *pstmt = CreateStmt();
	if(pstmt == NULL)
	{
		SetErr("Fail to create STMT Object");
		return ENG_ERROR;
	}
	if ( ENG_ERROR == pstmt->WriteReadSock(ITEM_COMMIT,STAT_END,REPLY_SERVER_OK,strlen("COMMIT_OK"),"COMMIT_OK"))
	{
			SetErr(pstmt->m_pPack->szData);
			if( NULL != pErr )
				*pErr = pstmt->m_szErr;
			pstmt->Finalize();
			return ENG_ERROR;
	}
	pstmt->Finalize();
	*/
	return ENG_OK;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// RollBack 수행.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL CDBC::RollBack(char** pErr)
{
	/*
	if(m_bOpen == FALSE)
		return ENG_ERROR;
	STMT *pstmt = CreateStmt();
	if(NULL ==  pstmt)
	{
		SetErr("Fail to create STMT Object");
		return ENG_ERROR;
	}
	if ( ENG_ERROR == pstmt->WriteReadSock(ITEM_ROLLBACK,STAT_END,REPLY_SERVER_OK,strlen("ROLLBACK_OK"),"ROLLBACK_OK"))
	{
			SetErr(pstmt->m_pPack->szData);
			if( NULL != pErr)
				*pErr = pstmt->m_szErr;
			pstmt->Finalize();
			return ENG_ERROR;
	}
	pstmt->Finalize();
	*/
	return ENG_OK;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Prepare 함수.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL CDBC::Prepare(const char * pSQL, int nByte, STMT ** ppStmt)
{
	CSTMT *pstmt = CreateStmt();
	*ppStmt = pstmt;
	if( pstmt == NULL)
		return ENG_ERROR;
	return pstmt->Prepare(pSQL);
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Error Code.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
int CDBC::ErrorCode()
{
	return ENG_ERROR;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Error Message.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
const char *CDBC::ErrMsg()
{
	return m_szErr;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// User Function.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
BOOL CDBC::UserFunc(const char *pszSQL)
{
	return TRUE;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Interrupt
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
void CDBC::Interrupt()
{
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Error Code
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
int  CDBC::ErrCode()
{
	return ENG_OK;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Error Code
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
int  CDBC::Changes()
{
	return ENG_OK;
}
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// Trace
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
int  CDBC::Trace(void(*xTrace)(void*,const char*), void* p)
{
	return 0;
}
